package com.hs;

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.al.common.json.Jackson2Converter;
import com.al.crm.nosql.cache.JsonSerializeObj;
import com.al.crm.nosql.cache.impl.RedisDBInfo;
import com.al.uniconfig.util.ObservablePropertyHolder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {
    private static Logger logger = LoggerFactory.getLogger(Utils.class);
    private static Jackson2Converter jsonConverter = Jackson2Converter.buildNormalConverter();
    private static List<String> KEY_WORD_AFTER_FROM_IN_SQL = new LinkedList();
    private static List<String> ABANDON_TABLE_NAME = new LinkedList();
    public static String CACHE_CLIENT_MODULE = new String("cacheClient");
    private static ObjectMapper mapper = new ObjectMapper();

    public Utils() {
    }

    public static Jackson2Converter getJsonConverter() {
        return jsonConverter;
    }

    public static Properties getProperties(Class<?> clz, String filename) throws IOException {
        Properties p = new Properties();
        if (filename == null) {
            return p;
        } else {
            URL url = null;
            url = clz.getResource(filename);
            if (url == null) {
                url = clz.getResource("/" + filename);
            }

            if (url == null) {
                url = ClassLoader.getSystemResource(filename);
            }

            if (url == null) {
                throw new IOException();
            } else {
                InputStream in = url.openStream();

                try {
                    p.load(in);
                } finally {
                    in.close();
                }

                return p;
            }
        }
    }

    public static boolean isBasicType(Class<?> type) {
        if (type.isPrimitive()) {
            return true;
        } else if (type == String.class) {
            return true;
        } else if (type == Integer.class) {
            return true;
        } else if (type == Long.class) {
            return true;
        } else if (type == Double.class) {
            return true;
        } else if (type == Float.class) {
            return true;
        } else if (type == Short.class) {
            return true;
        } else if (type == Byte.class) {
            return true;
        } else {
            return type == Boolean.class;
        }
    }

    public static <T> T getObjFromStr(String value, Class<T> type) throws IOException {
        if (type == String.class) {
            return type.cast(value);
        } else if (type == Integer.class) {
            return type.cast(Integer.parseInt(value));
        } else if (type == Long.class) {
            return type.cast(Long.parseLong(value));
        } else if (type == Double.class) {
            return type.cast(Double.parseDouble(value));
        } else if (type == Float.class) {
            return type.cast(Float.parseFloat(value));
        } else if (type == Short.class) {
            return type.cast(Short.parseShort(value));
        } else {
            return type == Boolean.class ? type.cast(Boolean.parseBoolean(value)) : getJsonConverter().toBean(value, type);
        }
    }

    public static String toCacheJson(Object obj) throws JsonProcessingException {
        JsonSerializeObj co = new JsonSerializeObj();
        co.setClz(obj.getClass().getName());
        co.setJson(mapper.writeValueAsString(obj));
        return mapper.writeValueAsString(co);
    }

    public static Object getRealObject(String json) throws IOException, ClassNotFoundException {
        JsonSerializeObj co = (JsonSerializeObj)mapper.readValue(json, JsonSerializeObj.class);
        Class<?> clz = Class.forName(co.getClz());
        return mapper.readValue(co.getJson(), clz);
    }

    public static Object getObjFromJson(String json) throws IOException, ClassNotFoundException {
        if (json == null) {
            return null;
        } else {
            ObjectMapper mapper = getJsonConverter().getMapper();
            JsonNode rootNode = mapper.readTree(json);
            JsonNode clzNode = rootNode.path("clz");
            JsonNode objNode = rootNode.path("obj");

            try {
                if (!clzNode.isMissingNode() && !objNode.isMissingNode()) {
                    if (!objNode.isArray()) {
                        Class<?> clz = Class.forName(clzNode.asText());
                        Object var12 = mapper.readValue(objNode.traverse(), clz);
                        return var12;
                    } else {
                        List list = new LinkedList();
                        if (objNode.size() > 0) {
                            Class<?> clz = Class.forName(clzNode.asText());

                            for(int i = 0; i < objNode.size(); ++i) {
                                list.add(mapper.readValue(objNode.get(i).traverse(), clz));
                            }
                        }

                        return list;
                    }
                } else {
                    return json;
                }
            } finally {
                ;
            }
        }
    }

    public static <T> T getObj(Object value, Class<T> type) throws IOException {
        return isBasicType(type) ? type.cast(value) : getJsonConverter().toBean((String)value, type);
    }

    public static boolean isPossibleJSON(String value) {
        if (value == null) {
            return false;
        } else if (value.trim().charAt(0) == '[' && value.trim().charAt(value.trim().length() - 1) == ']') {
            return true;
        } else {
            return value.trim().charAt(0) == '{' && value.trim().charAt(value.trim().length() - 1) == '}';
        }
    }

    public static RedisDBInfo getRedisDBInfoFromURI(String sUri, int timeout) {
        String regEx = "redis:\\/\\/(.*):(.*)@(.+):(\\d+)\\/(\\d+)";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(sUri);
        boolean rs = matcher.matches();
        if (rs) {
            String user = matcher.group(1);
            String password = matcher.group(2);
            String host = matcher.group(3);
            int port = Integer.parseInt(matcher.group(4));
            int database = Integer.parseInt(matcher.group(5));
            RedisDBInfo redisDBInfo = new RedisDBInfo();
            redisDBInfo.setHost(host);
            redisDBInfo.setPort(port);
            password = AESOperator.getInstance().decrypt(password);
            redisDBInfo.setPassword(password);
            redisDBInfo.setDb(database);
            redisDBInfo.setTimeout(timeout);
            return redisDBInfo;
        } else {
            throw new RuntimeException("不正确的redis配置地址: " + sUri);
        }
    }

    public static <T> List<T> getSubList(List<T> list, int offset, int limit) {
        if (limit < 0) {
            return list;
        } else {
            int fromIndex = offset * limit;
            int toIndex = offset * limit + limit;
            if (list.size() < fromIndex + 1) {
                return new LinkedList();
            } else {
                if (list.size() < toIndex) {
                    toIndex = list.size();
                }

                return list.subList(fromIndex, toIndex);
            }
        }
    }

    public static boolean isTableInSQL(String table, String sql) {
        String regexp = "\\s+from\\s+(.*\\." + table + "|" + table + ")\\b";
        Pattern pattern = Pattern.compile(regexp, 2);
        Matcher matcher = pattern.matcher(sql);
        return matcher.find();
    }

    public static String extractTableNameInUpdate(String sql) {
        if (sql == null) {
            return null;
        } else {
            String _sql = sql.trim().toLowerCase();
            StringTokenizer itr = new StringTokenizer(_sql);
            Object var3 = null;

            String word;
            do {
                if (!itr.hasMoreTokens()) {
                    return null;
                }

                word = itr.nextToken();
            } while(!"update".equals(word));

            return itr.nextToken();
        }
    }

    public static String extractTableNameInInsert(String sql) {
        if (sql == null) {
            return null;
        } else {
            String _sql = sql.trim().toLowerCase();
            StringTokenizer itr = new StringTokenizer(_sql);

            while(itr.hasMoreTokens()) {
                String word = itr.nextToken();
                if ("insert".equals(word)) {
                    word = itr.nextToken();
                    if ("into".equals(word)) {
                        return itr.nextToken();
                    }
                }
            }

            return null;
        }
    }

    public static String extractTableNameInDelete(String sql) {
        if (sql == null) {
            return null;
        } else {
            String _sql = sql.trim().toLowerCase();
            StringTokenizer itr = new StringTokenizer(_sql);

            while(itr.hasMoreTokens()) {
                String word = itr.nextToken();
                if ("delete".equals(word)) {
                    word = itr.nextToken();
                    if ("from".equals(word)) {
                        return itr.nextToken();
                    }
                }
            }

            return null;
        }
    }

    public static List<String> extractTableNameInSelect(String sql) {
        List<String> tabList = new LinkedList();
        List<String> sqlList = exstractQrySubClause(sql);
        Iterator i$ = sqlList.iterator();

        while(i$.hasNext()) {
            String oneSql = (String)i$.next();
            List<String> tabInOneList = extractTableNameInOneSelect(oneSql);
            tabList.addAll(tabInOneList);
        }

        return tabList;
    }

    public static List<String> extractTableNameInOneSelect(String sql) {
        if (sql == null) {
            return null;
        } else {
            String _sql = sql.trim().toLowerCase();
            StringTokenizer itr = new StringTokenizer(_sql, " \t\n\r\f,", true);
            List<String> tabList = new LinkedList();
            String preWord = null;

            while(true) {
                String word;
                do {
                    if (!itr.hasMoreTokens()) {
                        return tabList;
                    }

                    word = itr.nextToken();
                } while(word.trim().length() == 0);

                if ("from".equals(word)) {
                    LinkedList wordList = new LinkedList();

                    while(itr.hasMoreTokens()) {
                        String afterFrom = itr.nextToken();
                        if (afterFrom.trim().length() != 0) {
                            if (afterFrom.trim().startsWith("(") || KEY_WORD_AFTER_FROM_IN_SQL.contains(afterFrom) || ABANDON_TABLE_NAME.contains(afterFrom)) {
                                break;
                            }

                            wordList.add(afterFrom);
                        }
                    }

                    for(int i = 0; i < wordList.size(); ++i) {
                        if (i == 0 && !tabList.contains(wordList.get(0)) && !ABANDON_TABLE_NAME.contains(wordList.get(0))) {
                            tabList.add(wordList.get(0));
                        } else if (",".equals(wordList.get(i)) && i + 1 < wordList.size() && !tabList.contains(wordList.get(i + 1)) && !ABANDON_TABLE_NAME.contains(wordList.get(i + 1))) {
                            tabList.add(wordList.get(i + 1));
                        }
                    }
                }

                if ("join".equals(word) && preWord != null && (preWord.equals("inner") || preWord.equals("left") || preWord.equals("right") || preWord.equals("outer"))) {
                    while(itr.hasMoreElements()) {
                        String table = itr.nextToken();
                        if (table.trim().length() != 0 && !tabList.contains(table) && !ABANDON_TABLE_NAME.contains(table)) {
                            tabList.add(table);
                            break;
                        }
                    }
                }

                preWord = word;
            }
        }
    }

    public static List<String> exstractQrySubClause(String sql) {
        List<String> sqlList = new LinkedList();
        int pCount = 0;
        int leftPIdx = sql.indexOf(40);
        if (leftPIdx < 0) {
            sqlList.add(sql);
        } else {
            while(true) {
                if (leftPIdx >= 0) {
                    if (!sql.substring(leftPIdx + 1).startsWith("select")) {
                        leftPIdx = sql.indexOf(40, leftPIdx + 1);
                        continue;
                    }

                    int nextLeftPIdx = sql.indexOf(40, leftPIdx + 1);
                    int rightPIdx = sql.indexOf(41, leftPIdx + 1);
                    if (nextLeftPIdx >= 0 && nextLeftPIdx < rightPIdx) {
                        int pCount = pCount + 1;

                        for(int i = leftPIdx + 1; i < sql.length(); ++i) {
                            if (sql.charAt(i) == '(') {
                                ++pCount;
                            } else if (sql.charAt(i) == ')') {
                                --pCount;
                                if (pCount == 0) {
                                    rightPIdx = i;
                                    break;
                                }
                            }
                        }
                    }

                    String sql1 = sql.substring(0, leftPIdx + 1) + sql.substring(rightPIdx);
                    sqlList.addAll(exstractQrySubClause(sql1));
                    String sql2 = sql.substring(leftPIdx + 1, rightPIdx);
                    sqlList.addAll(exstractQrySubClause(sql2));
                }

                if (sqlList.size() == 0) {
                    sqlList.add(sql);
                }
                break;
            }
        }

        return sqlList;
    }

    public static Method getDeclaredMethod(Class<?> clazz, String methodName, Class... paramTypes) {
        return ReflectionUtils.findMethod(clazz, methodName, paramTypes);
    }

    public static Object[] getParamArray(Method method, Object... args) {
        if (args.length == 0) {
            return args;
        } else {
            Object[] objs = new Object[method.getParameterTypes().length];

            for(int i = 0; i < method.getParameterTypes().length; ++i) {
                Class<?> clz = method.getParameterTypes()[i];
                if (!clz.isArray()) {
                    objs[i] = args[i];
                } else {
                    if (!args[i].getClass().isArray()) {
                        Object arr = Array.newInstance(args[i].getClass(), args.length - i);

                        for(int j = i; j < method.getParameterTypes().length; ++j) {
                            Array.set(arr, j - i, args[j]);
                        }

                        objs[i] = arr;
                        break;
                    }

                    objs[i] = args[i];
                }
            }

            return objs;
        }
    }

    public static String checkAndRebuildTopDir(String dir) {
        String topDir = dir;
        if (dir != null) {
            if (!dir.startsWith("/")) {
                topDir = "/" + dir;
            }

            if (!topDir.endsWith("/")) {
                topDir = topDir + "/";
            }
        }

        return topDir;
    }

    public static String contractDir(String upDir, String subDir) {
        String resDir;
        if (upDir.endsWith("/")) {
            if (!subDir.startsWith("/")) {
                resDir = upDir + subDir;
            } else {
                resDir = upDir + subDir.substring("/".length());
            }
        } else if (!subDir.startsWith("/")) {
            resDir = upDir + "/" + subDir;
        } else {
            resDir = upDir + subDir;
        }

        return resDir;
    }

    public static String checkAndRebuildSubDir(String dir) {
        String subDir = dir;
        if (dir != null) {
            if (dir.startsWith("/")) {
                subDir = dir.substring("/".length());
            }

            if (!subDir.endsWith("/")) {
                subDir = subDir + "/";
            }
        }

        return subDir;
    }

    public static void overrideTargetProp(Properties srcProps, Map targetMap) {
        if (targetMap == null) {
            throw new IllegalArgumentException("Map must not be null");
        } else {
            if (srcProps != null) {
                Iterator i$ = targetMap.keySet().iterator();

                while(i$.hasNext()) {
                    Object key = i$.next();
                    Object value = srcProps.get(key);
                    if (value == null) {
                        targetMap.put(key, value);
                    }
                }
            }

        }
    }

    public static void overrideFromUniConfig(Properties prop) {
        if (prop == null) {
            throw new IllegalArgumentException("prop must not be null");
        } else {
            Properties propInMem = ObservablePropertyHolder.getProperties(CACHE_CLIENT_MODULE);
            String keyPrefix = ObservablePropertyHolder.getDomainName() + ObservablePropertyHolder.getSeparatorInPropKey() + CACHE_CLIENT_MODULE + ObservablePropertyHolder.getSeparatorInPropKey();

            String rawKey;
            String rawVal;
            for(Enumeration en = propInMem.propertyNames(); en.hasMoreElements(); prop.put(rawKey, rawVal)) {
                String key = (String)en.nextElement();
                rawKey = key.substring(keyPrefix.length());
                rawVal = propInMem.getProperty(key);
                if (prop.containsKey(rawKey)) {
                    logger.info("Prop key {} will be overrided by prop key {} from UniCfg! new value is {}", new String[]{rawKey, key, rawVal});
                }
            }

        }
    }

    public static void overrideFromUniConfig(Properties srcProp, Properties targetProp) {
        if (targetProp == null) {
            throw new IllegalArgumentException("targetProp must not be null");
        } else {
            String keyPrefix = ObservablePropertyHolder.getDomainName() + ObservablePropertyHolder.getSeparatorInPropKey() + CACHE_CLIENT_MODULE + ObservablePropertyHolder.getSeparatorInPropKey();

            String key;
            String rawKey;
            for(Enumeration en = srcProp.propertyNames(); en.hasMoreElements(); targetProp.put(rawKey, srcProp.getProperty(key))) {
                key = (String)en.nextElement();
                rawKey = key.substring(keyPrefix.length());
                if (targetProp.containsKey(rawKey)) {
                    logger.info("Prop key {} will be overrided by prop key {} from UniCfg!", rawKey, key);
                }
            }

        }
    }

    public static String generateKey(String className, String methodName, Object args) {
        if (args == null) {
            return className + "." + methodName;
        } else {
            return args.getClass().isArray() && Array.getLength(args) == 0 ? className + "." + methodName : className + "." + methodName + "." + "HC" + (new HashCodeBuilder()).append(args).toHashCode();
        }
    }

    public static String generateKey(String className, String methodName, Object args, String suffix) {
        return generateKey(className, methodName, args) + "_" + suffix;
    }

    public static <T> T[] ArraysCopyOf(T[] ars, int start) {
        T[] newars = (Object[])((Object[])Array.newInstance(ars.getClass().getComponentType(), ars.length - start));
        System.arraycopy(ars, start, newars, 0, newars.length);
        return newars;
    }

    static {
        KEY_WORD_AFTER_FROM_IN_SQL.add("where");
        KEY_WORD_AFTER_FROM_IN_SQL.add("start");
        KEY_WORD_AFTER_FROM_IN_SQL.add("inner");
        KEY_WORD_AFTER_FROM_IN_SQL.add("left");
        KEY_WORD_AFTER_FROM_IN_SQL.add("right");
        KEY_WORD_AFTER_FROM_IN_SQL.add("order");
        KEY_WORD_AFTER_FROM_IN_SQL.add("group");
        ABANDON_TABLE_NAME.add("dual");
    }
}
